feat(developer): kmc convert typesafety 😎#15860
Conversation
User Test ResultsTest specification and instructions User tests are not required Test Artifacts
|
…b.com/keymanapp/keyman into feat/developer/kmc-convert-Typesafety
…vert-Typesafety # Conflicts: # developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-to-kmn-converter.ts # developer/src/kmc-convert/src/keylayout-to-kmn/kmn-file-writer.ts # developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts # developer/src/kmc-convert/test/kmn-file-writer.tests.ts
| * @brief helper function to check if a specific keyMap index exists in a keyMapSet | ||
| * neccessary because the amount of <keyMap index> must correspond to | ||
| * the amount of <keyMapSelect mapIndex> |
There was a problem hiding this comment.
It would be better to make this full sentences. If this gets processed by a tool the three lines might get put in the same paragraph removing the line breaks, which then would make it hard to understand.
| * @brief helper function to check if a specific keyMap index exists in a keyMapSet | |
| * neccessary because the amount of <keyMap index> must correspond to | |
| * the amount of <keyMapSelect mapIndex> | |
| * @brief Helper function to check if a specific keyMap index exists in a keyMapSet. | |
| * This is neccessary because the amount of <keyMap index> must correspond to | |
| * the amount of <keyMapSelect mapIndex>. |
| * @brief helper function to check if a specific keyMapSelect index exists in a modifierMap | ||
| * neccessary because the amount of <keyMap index> must correspond to | ||
| * the amount of <keyMapSelect mapIndex> |
There was a problem hiding this comment.
| * @brief helper function to check if a specific keyMapSelect index exists in a modifierMap | |
| * neccessary because the amount of <keyMap index> must correspond to | |
| * the amount of <keyMapSelect mapIndex> | |
| * @brief Helper function to check if a specific keyMapSelect index exists in a modifierMap. | |
| * This is neccessary because the amount of <keyMap index> must correspond to | |
| * the amount of <keyMapSelect mapIndex>. |
| behavior: string; | ||
| modifier?: string; | ||
| outchar?: string; | ||
| outchar?: string | undefined; |
There was a problem hiding this comment.
This should not be necessary. outchar? makes the property optional which implies undefined. So if you write outchar?: string; the type of outchar is implicitly string|undefined.
| // in case writeCharacterOrUnicode() returns null, the fallback is empty strings for characterMessage.character | ||
| // and characterMessage.message. Then versionOutputCharacter could be "" and would be written into the kmn file | ||
| // as ... > '', producing an invalid kmn rule. |
There was a problem hiding this comment.
I don't understand this comment. It describes what the code does and that this could result in an invalid kmn rule. Wouldn't we want to do something so that we don't get invalid kmn rules? (in which case I'd expect a TODO or something).
Or does the comment try to explain why we have the if ((outputCharacter !== undefined) && (outputCharacter !== "")) check? Then it should mention outputCharacter which could lead to writeCharacterOrUnicode returning false...
(Additional occurrences of the same code comment above)
| * null in case of an empty string or null or undefined input | ||
| */ | ||
| public writeCharacterOrUnicode(ctr: string, msg: string = ""): MessageCharacter { | ||
| public writeCharacterOrUnicode(ctr: string, msg: string = ""): MessageCharacter | null { |
There was a problem hiding this comment.
I think it would be better if writeCharacterToUnicode would always returns MessageCharacter. In the error case it could return { character: '', message: '' }. IMO this would simplify things quite a bit.
| ].forEach(function (values) { | ||
| it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[2] + '"', async function () { | ||
| const result = sutW.writeCharacterOrUnicode(values[0] as string, values[1] as string); | ||
| if (result) { |
There was a problem hiding this comment.
It would be better to split this into two tests: one set that tests the cases where we get a result, and the other for the cases that return null.
| }); | ||
| it(('null should create empty string '), async function () { | ||
| const result1 = sutW.writeDataRules(null); | ||
| assert.isTrue(result1 === ''); |
There was a problem hiding this comment.
I'd use
| assert.isTrue(result1 === ''); | |
| assert.equal(result1, ''); |
| it('run() should throw on unavailable input file name and null output file name', async function () { | ||
| const inputFilename = makePathToFixture('../data/Unavailable.keylayout'); | ||
| const result = sut.run(inputFilename, null); | ||
| const result = sut.run(inputFilename, undefined); |
There was a problem hiding this comment.
Since run is async, we'll have to await it:
| const result = sut.run(inputFilename, undefined); | |
| const result = await sut.run(inputFilename, undefined); |
| this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({ | ||
| keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'], | ||
| output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] ?? '', | ||
| output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] ?? '' as string, |
There was a problem hiding this comment.
as string is unnecessary since it's already a string.
| output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] ?? '' as string, | |
| output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] ?? '', |
|
|
||
| // use of Unicode Character vs Unicode Codepoint; | ||
| // If it`s a ctrl character we print out the Unicode Codepoint else we print out the Unicode Character | ||
| let versionOutputCharacter; |
There was a problem hiding this comment.
Might be better to initialize this to the empty string, otherwise we could theoretically end up with an uninitialized variable if the if in line 163 evaluates to false.
| let versionOutputCharacter = ''; |
In several places in kmc-convert: keylayout->kmn we did not care about return type null or undefined for function return values or parameters. Therefore we got several warnings about possible return types not being assignable to symbols.
Even though they did not affect the code running correctly they have been specified more clearly in this PR.
@keymanapp-test-bot skip
see also: